package car_rental.dao;

import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.metamodel.Metamodel;

public class LocalThreadEntityManager implements EntityManager {
	private final EntityManager delegate;
	private int referenceCount = 0;

	public LocalThreadEntityManager(final EntityManager delegate) {
		this.delegate = delegate;
		this.referenced();
	}

	/**
	 * Increase internal reference counter.
	 */
	public void referenced() {
		referenceCount++;
	}
		
	@Override
	public void clear() {
		delegate.clear();
	}
	
	@Override
	public void close() {
		if (--referenceCount == 0) {
			delegate.close();
		}
	}

	@Override
	public boolean contains(Object arg0) {
		return delegate.contains(arg0);
	}

	@Override
	public Query createNamedQuery(String arg0) {
		return delegate.createNamedQuery(arg0);
	}

	@Override
	public <T> TypedQuery<T> createNamedQuery(String arg0, Class<T> arg1) {
		return delegate.createNamedQuery(arg0,arg1);
	}

	@Override
	public Query createNativeQuery(String arg0) {
		return delegate.createNativeQuery(arg0);
	}

	@Override
	public Query createNativeQuery(String arg0, @SuppressWarnings("rawtypes") Class arg1) {
		return delegate.createNativeQuery(arg0, arg1);
	}

	@Override
	public Query createNativeQuery(String arg0, String arg1) {
		return delegate.createNativeQuery(arg0, arg1);
	}

	@Override
	public Query createQuery(String arg0) {
		return delegate.createQuery(arg0);
	}

	@Override
	public <T> TypedQuery<T> createQuery(CriteriaQuery<T> arg0) {
		return delegate.createQuery(arg0);
	}

	@Override
	public <T> TypedQuery<T> createQuery(String arg0, Class<T> arg1) {
		return delegate.createQuery(arg0, arg1);
	}

	@Override
	public void detach(Object arg0) {
		delegate.detach(arg0);
	}

	@Override
	public <T> T find(Class<T> arg0, Object arg1) {
		return delegate.find(arg0, arg1);
	}

	@Override
	public <T> T find(Class<T> arg0, Object arg1, Map<String, Object> arg2) {
		return delegate.find(arg0, arg1, arg2);
	}

	@Override
	public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2) {
		return delegate.find(arg0, arg1, arg2);
	}

	@Override
	public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2, Map<String, Object> arg3) {
		return delegate.find(arg0, arg1, arg2, arg3);
	}

	@Override
	public void flush() {
		delegate.flush();
	}

	@Override
	public CriteriaBuilder getCriteriaBuilder() {
		return delegate.getCriteriaBuilder();
	}

	@Override
	public Object getDelegate() {
		return delegate.getDelegate();
	}

	@Override
	public EntityManagerFactory getEntityManagerFactory() {
		return delegate.getEntityManagerFactory();
	}

	@Override
	public FlushModeType getFlushMode() {
		return delegate.getFlushMode();
	}

	@Override
	public LockModeType getLockMode(Object arg0) {
		return delegate.getLockMode(arg0);
	}

	@Override
	public Metamodel getMetamodel() {
		return delegate.getMetamodel();
	}

	@Override
	public Map<String, Object> getProperties() {
		return delegate.getProperties();
	}

	@Override
	public <T> T getReference(Class<T> arg0, Object arg1) {
		return delegate.getReference(arg0, arg1);
	}

	@Override
	public EntityTransaction getTransaction() {
		return delegate.getTransaction();
	}

	@Override
	public boolean isOpen() {
		return delegate.isOpen();
	}

	@Override
	public void joinTransaction() {
		delegate.joinTransaction();
	}

	@Override
	public void lock(Object arg0, LockModeType arg1) {
		delegate.lock(arg0, arg1);
	}

	@Override
	public void lock(Object arg0, LockModeType arg1, Map<String, Object> arg2) {
		delegate.lock(arg0, arg1, arg2);
	}

	@Override
	public <T> T merge(T arg0) {
		return delegate.merge(arg0);
	}

	@Override
	public void persist(Object arg0) {
		delegate.persist(arg0);
	}

	@Override
	public void refresh(Object arg0) {
		delegate.refresh(arg0);
	}

	@Override
	public void refresh(Object arg0, Map<String, Object> arg1) {
		delegate.refresh(arg0, arg1);
	}

	@Override
	public void refresh(Object arg0, LockModeType arg1) {
		delegate.refresh(arg0, arg1);
	}

	@Override
	public void refresh(Object arg0, LockModeType arg1, Map<String, Object> arg2) {
		delegate.refresh(arg0, arg1, arg2);
	}

	@Override
	public void remove(Object arg0) {
		delegate.remove(arg0);
	}

	@Override
	public void setFlushMode(FlushModeType arg0) {
		delegate.setFlushMode(arg0);
	}

	@Override
	public void setProperty(String arg0, Object arg1) {
		delegate.setProperty(arg0, arg1);
	}

	@Override
	public <T> T unwrap(Class<T> arg0) {
		return delegate.unwrap(arg0);
	}
}
